package ar.com.photo_admin.domain

import org.grails.plugins.imagetools.ImageTool
import org.springframework.dao.DataIntegrityViolationException
import javax.servlet.http.HttpServletResponse;

class UserController {
	
    static allowedMethods = [save: "POST", update: "POST", delete: "POST", changeProfileImage: "POST"]

	final int PROFILE_IMAGE_SIZE = 150
	
	final EMPTY_PAGE_ON_AJAX_RESPONSE = ""
	
	final RELOAD_PAGE_ON_AJAX_RESPONSE = "<script type='text/javascript'> javascript: scroll(0, 0); window.location.reload(); </script>"
	
	def DEFAULT_PROFILE_IMAGE_PATH = System.properties['base.dir'] + '/web-app/images/defaultProfile.png'
	def DEFAULT_PROFILE_IMAGE_CONTENT_TYPE = 'image/png'
	
	def facebookUserService

	def userService
		
	def simpleCaptchaService

	def facebookLogin() {
		
		def facebookId = session.facebook?.uid 
		
		if (facebookId) {
			
			if (!facebookUserService.isUserRegistered(facebookId)) {
				User user = facebookUserService.getUserData(facebookId)
				render(template: "facebookSignin", model: [user: user])
			} else {
				session.user = facebookUserService.findUserByFacebookId(facebookId)
				render RELOAD_PAGE_ON_AJAX_RESPONSE
			}			
		}
		else
			return params
	}
	
	def facebookSignin() {
		
		def facebookId = session.facebook?.uid
		
		if (facebookId) {
			User user = new User(params)
			user.facebookUid = facebookId
			signIn(user, "facebookSignin")
		}
		else
			return params
	}
	
	def siteLogin() {

		UserLogin userLogin = new UserLogin(params) 
				
		if (userLogin.validate()) {
			session.user = userService.findByUsernameOrEmail(userLogin.userId)
			render RELOAD_PAGE_ON_AJAX_RESPONSE
		} else {
			userLogin.password = ""
			render(template: "siteLogin", model: [userLogin: userLogin])
		}		
	}
	
	def siteSignin() {
		User user = new User(params)
		signIn(user, "siteSignin")
	}
	
	private def signIn(User user, String templateId) {
		
		/*
		 * Transient domain properties cannot be set in the Domain objects constructor.
		 */
		user.confirmPassword = params.confirmPassword
		user.captchaCode = params.captchaCode
		
		/*
		 * TODO Put this somewhere else?
		 */
		if (!user.profileImageUrl) {
			user.profileImageUrl = g.createLinkTo(dir:"images", file:"defaultProfile.png").toString()
		}
		
		user.validate()
				
		boolean captchaValid = simpleCaptchaService.validateCaptcha(user.captchaCode)
		if (!captchaValid)
			user.errors.rejectValue("captchaCode", "user.captcha.invalid")
		
		if (captchaValid && userService.save(user)) {
			session.user = user
			render RELOAD_PAGE_ON_AJAX_RESPONSE
		} else {
			user.password = ""
			user.confirmPassword = ""
			user.captchaCode = ""
			render(template: templateId, model: [user: user])
		}
	}

	def showProfile() {
		
		def id = session.user?.id
		
		if (id) {
			def user = User.get(id)
			[user: user]
		} else {
			redirect(uri: '/')
		}		
	}
	
	def saveProfile() {
		User user = User.get(session.user?.id)
		
		if (user) {
			user.properties = params
			_validateCaptcha(user)
			
			if (!user.hasErrors() && userService.save(user)) {
				flash.message = message(code: 'user.profile.update')
				redirect(action: "showProfile")
			} else {
				user.captchaCode = ""
				render(view: "showProfile", model: [user: user])			
			}				
			
		} else
			redirect(uri: '/')
	}
	
	def changePassword() {
		User user = User.get(session.user?.id)
				
		if (user && user.password) {
			_changeOrGeneratePassword(user, "changePassword", "user.profile.change.password.message")
		} else
			render RELOAD_PAGE_ON_AJAX_RESPONSE
	}

	def generatePassword() {
		User user = User.get(session.user?.id)
		
		if (user && !user.password) {
			params.oldPassword = user.password
			_changeOrGeneratePassword(user, "generatePassword", "user.profile.generate.password.message")
		} else
			render RELOAD_PAGE_ON_AJAX_RESPONSE
	}
	
	def _changeOrGeneratePassword(User user, String templateId, String successMessageCode) {
		
		if (user.password.equals(params.oldPassword)) {
			
			user.password = params.password
			user.confirmPassword = params.confirmPassword
			
			if (userService.save(user)) {
				flash.message = message(code: successMessageCode)
				render RELOAD_PAGE_ON_AJAX_RESPONSE
			}
			else {
				render(template: templateId, model: [user: user])
			}
		} else {
			user.errors.rejectValue("oldPassword", "user.profile.change.password.invalid")
			render(template: templateId, model: [user: user])
		}
	}
	
	def detachFacebookAccount() {
		
		User user = User.get(session.user?.id)
		
		if (user) {
			
			if (!user.facebookUid) 
				flash.error = message(code: "user.profile.social.networks.facebook.detach.fail.facebook")
			else if (!user.password) {
				flash.error = message(code: "user.profile.social.networks.facebook.detach.fail.password")
			} else {
				session.facebook = null
				user.facebookUid = null
						
				if (userService.save(user))
					flash.message = message(code: "user.profile.social.networks.facebook.detach.success")
			}			

			redirect(action: "showProfile")
		} else
			redirect(uri: '/')
	}
	
	def attachFacebookAccount() {
		
		User user = User.get(session.user?.id)
		def facebookId = session.facebook?.uid
		
		if (user && facebookId) {
			
			if (user.facebookUid)
				flash.error = message(code: "user.profile.social.networks.facebook.attach.fail.facebook")
			else if (facebookUserService.isUserRegistered(facebookId)) {
				flash.error = message(code: "user.facebookUid.unique")
			} else {
				user.facebookUid = facebookId
						
				if (userService.save(user))
					flash.message = message(code: "user.profile.social.networks.facebook.attach.success")
			}

			redirect(action: "showProfile")
		} else
			redirect(uri: '/')
	}
	
	def uploadProfileImage() {
		
		User user = User.get(session.user?.id)
		
		if (user) {
			def image = request.getFile('imageFile')
			
			def okContents = ['image/png', 'image/jpeg', 'image/gif']
			
			if (!image.empty && !okContents.contains(image.getContentType()))
				flash.error = message(code: "user.profile.image.invalid.extension")
			else {
			
				try {
					ImageTool imageTool = new ImageTool()
					imageTool.load(image.getBytes())
					imageTool.square()
					imageTool.swapSource()
					imageTool.thumbnail(PROFILE_IMAGE_SIZE)
					
					user.profileImage = imageTool.getBytes("JPEG")
					user.profileImageType = 'image/jpeg'
					
					boolean useFacebook = user.useFacebookProfileImage;
					if (useFacebook)
						user.useFacebookProfileImage = false;
					
					if (userService.save(user)) {
						if (useFacebook)
							flash.message = message(code: "user.profile.image.facebook.unchecked2")
						else
							flash.message = message(code: "user.profile.image.update.success")
						
					} else
						flash.error = message(code: "user.profileImage.maxSize.exceeded")
						
				} catch (Exception e) {
					flash.error = message(code: "user.profile.image.invalid.damage")
				}
			}
							
			redirect(action: "showProfile")			
		} else
			redirect(uri: '/')
	}
	
	def profileImage = {
		
		User user = User.get(params.id)
		
		if (user.useFacebookProfileImage) {
			def imageUrl = facebookUserService.getProfilePhotoSrc(user.facebookUid) + "?type=large"
			redirect(url : imageUrl)
		}		
		else if (user.profileImageType && user.profileImage) {
	
			response.setContentType(user.profileImageType)
			response.setContentLength(user.profileImage.size())
			OutputStream out = response.getOutputStream();
			out.write(user.profileImage);
			out.close();
					
		} else
			response.sendError(404)
	}
	
	def useFacebookProfileImage() {
		
		User user = User.get(session.user?.id)
		
		if (user) {
			
			user.useFacebookProfileImage = !user.useFacebookProfileImage
			
			if (userService.save(user)) {
				if (user.useFacebookProfileImage)
					flash.message = message(code: "user.profile.image.facebook.checked")
				else
					flash.message = message(code: "user.profile.image.facebook.unchecked")
			} else
				flash.error = message(code: "user.profile.image.facebook.fail")
				
			redirect(action: "showProfile")
		} else
			redirect(uri: '/')
	}
	
	def renderProfileImageSelector() {
		render(template: "profileImageSelector")
	}
		
	def _validateCaptcha(User user) {
		boolean captchaValid = simpleCaptchaService.validateCaptcha(user.captchaCode)
		if (!captchaValid)
			user.errors.rejectValue("captchaCode", "user.captcha.invalid")
	}
	
	def renderSiteSigninTemplate() {
		render(template: "siteSignin")
	}
	
	def renderSiteLoginTemplate() {
		render(template: "siteLogin")
	}
	
	def logout() {
		session.facebook = null
		session.invalidate()
		redirect(uri: '/')
	}
	
    def index() {
        redirect(action: "list", params: params)
    }

    def list() {
        params.max = Math.min(params.max ? params.int('max') : 10, 100)
        [userInstanceList: User.list(params), userInstanceTotal: User.count()]
    }

    def create() {
        [userInstance: new User(params)]
    }

    def save() {
        def userInstance = new User(params)
        if (!userInstance.save(flush: true)) {
            render(view: "create", model: [userInstance: userInstance])
            return
        }

		flash.message = message(code: 'default.created.message', args: [message(code: 'user.label', default: 'User'), userInstance.id])
        redirect(action: "show", id: userInstance.id)
    }

    def show() {
        def userInstance = User.get(params.id)
        if (!userInstance) {
			flash.message = message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])
            redirect(action: "list")
            return
        }

        [userInstance: userInstance]
    }

    def edit() {
        def userInstance = User.get(params.id)
        if (!userInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])
            redirect(action: "list")
            return
        }

        [userInstance: userInstance]
    }

    def update() {
        def userInstance = User.get(params.id)
        if (!userInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])
            redirect(action: "list")
            return
        }

        if (params.version) {
            def version = params.version.toLong()
            if (userInstance.version > version) {
                userInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
                          [message(code: 'user.label', default: 'User')] as Object[],
                          "Another user has updated this User while you were editing")
                render(view: "edit", model: [userInstance: userInstance])
                return
            }
        }

        userInstance.properties = params

        if (!userInstance.save(flush: true)) {
            render(view: "edit", model: [userInstance: userInstance])
            return
        }

		flash.message = message(code: 'default.updated.message', args: [message(code: 'user.label', default: 'User'), userInstance.id])
        redirect(action: "show", id: userInstance.id)
    }

    def delete() {
        def userInstance = User.get(params.id)
        if (!userInstance) {
			flash.message = message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])
            redirect(action: "list")
            return
        }

        try {
            userInstance.delete(flush: true)
			flash.message = message(code: 'default.deleted.message', args: [message(code: 'user.label', default: 'User'), params.id])
            redirect(action: "list")
        }
        catch (DataIntegrityViolationException e) {
			flash.message = message(code: 'default.not.deleted.message', args: [message(code: 'user.label', default: 'User'), params.id])
            redirect(action: "show", id: params.id)
        }
    }
}
